#include "ota_version.h"
#define VERSION_URL_INFO "http://192.168.55.72:8080/ota/ota_version.json"
#define VERSION_URL_SW "http://192.168.55.72:8080/ota/gateway"
#define CUR_VERSION "{\"major\": 1, \"min\": 0, \"patch\": 0}"
#define GATE_PATH "/usr/bin/gateway.update"
typedef struct
{
    int major;
    int min;
    int patch;
    char *sha1;

} Url_info;
//{"major":1,"min":1,"patch":0,"sha1":""}
static void Ota_Version_ParseJson(char *json, Url_info *info)
{
    cJSON *root = cJSON_Parse(json);
    info->major = cJSON_GetObjectItem(root, "major")->valueint;
    info->min = cJSON_GetObjectItem(root, "min")->valueint;
    info->patch = cJSON_GetObjectItem(root, "patch")->valueint;
    cJSON *sha1item = cJSON_GetObjectItem(root, "sha1");
    if (sha1item)
    {
        info->sha1 = strdup(sha1item->valuestring);
    }
    cJSON_Delete(root);
}
/**
 * 获取文件的SHA1哈希值（40位16进制字符串）
 * 相同文件返回相同的哈希值，可用于判断文件是否相同
 * linux命令生成：sha1sum 文件名
 * 此函数可以利用AI工具帮我们生成
 */
static char *get_file_sha(char *filepath)
{
    FILE *file = fopen(filepath, "rb");
    if (!file)
    {
        perror("Failed to open file");
        return NULL;
    }

    unsigned char hash[SHA_DIGEST_LENGTH];
    SHA_CTX sha1;
    SHA1_Init(&sha1);

    const int bufSize = 32768;
    unsigned char *buffer = (unsigned char *)malloc(bufSize);
    if (!buffer)
    {
        perror("Failed to allocate memory");
        fclose(file);
        return NULL;
    }

    int bytesRead;
    while ((bytesRead = fread(buffer, 1, bufSize, file)) > 0)
    {
        SHA1_Update(&sha1, buffer, bytesRead);
    }

    SHA1_Final(hash, &sha1);
    fclose(file);
    free(buffer);

    char *outputBuffer = (char *)malloc(SHA_DIGEST_LENGTH * 2 + 1);
    if (!outputBuffer)
    {
        perror("Failed to allocate memory");
        return NULL;
    }

    for (int i = 0; i < SHA_DIGEST_LENGTH; i++)
    {
        sprintf(outputBuffer + (i * 2), "%02x", hash[i]);
    }

    return outputBuffer;
}
// int get_file_sha1(const char *filename, unsigned char *hash)
// {
//     if (!filename || !hash)
//     {
//         return -1;
//     }

//     FILE *file = fopen(filename, "rb");
//     if (!file)
//     {
//         perror("fopen failed");
//         return -1;
//     }

//     SHA_CTX sha_context;
//     if (SHA1_Init(&sha_context) != 1)
//     {
//         fclose(file);
//         return -1;
//     }

//     unsigned char buffer[4096];
//     size_t bytes_read;

//     while ((bytes_read = fread(buffer, 1, sizeof(buffer), file)) > 0)
//     {
//         if (SHA1_Update(&sha_context, buffer, bytes_read) != 1)
//         {
//             fclose(file);
//             return -1;
//         }
//     }

//     if (ferror(file))
//     {
//         perror("文件读取错误");
//         fclose(file);
//         return -1;
//     }

//     if (SHA1_Final(hash, &sha_context) != 1)
//     {
//         fclose(file);
//         return -1;
//     }

//     fclose(file);
//     return 0;
// }
GateState_t Ota_Version_CheckUpdata(void)
{
    Url_info newversion;  // 新版本
    Url_info currversion; // 当前版本
    // 从服务器中获取版本信息
    char *newversion_json = Ota_Http_GetVersionInfo(VERSION_URL_INFO);
    // 解析json将结构体变量中赋值
    Ota_Version_ParseJson(newversion_json, &newversion);
    Ota_Version_ParseJson(CUR_VERSION, &currversion);
    // 通过版本号判断是否要进行升级
    if ((currversion.major >= newversion.major) || ((currversion.major == newversion.major) && (currversion.min >= newversion.min)) || ((currversion.major == newversion.major) && (currversion.min >= newversion.min) && (currversion.patch >= newversion.patch)))
    {
        log_info("版本不需要升级");
        return GATE_OK;
    }
    // 经行升级
    log_info("版本需要升级");
    GateState_t status = Ota_Http_DownLoad(VERSION_URL_SW, GATE_PATH);
    if (status == GATE_ERROR)
    {
        log_error("版本下载失败");
        return GATE_ERROR;
    }
    // 比较哈希值
    // log_info("1");
    // char * currsha1;
    // log_info("2");
    // get_file_sha1((const char *)GATE_PATH, (unsigned char*)currsha1);
    // log_info("3");
    char *currsha1 = get_file_sha(GATE_PATH);

    char *newsha1 = newversion.sha1;
    log_info("%s", currsha1);
    log_info("%s", newsha1);
    if (strcmp(currsha1, newsha1) != 0)
    {
        log_error("哈希值比较失败");
        return GATE_ERROR;
    }
    log_info("哈希值验证成功");
    free(currsha1);
    free(newversion_json);
    return GATE_OK;
}